Vuetify is a popular UI framework for Vue apps.
In this article, we’ll look at how to work with the Vuetify framework.
Editable Table Columns
We can add the v-edit-dialog
component to make some columns editable.
For example, we can write:
<template>
<div>
<v-data-table :headers="headers" :items="desserts">
<template v-slot:item.name="props">
<v-edit-dialog
:return-value.sync="props.item.name"
@save="save"
@cancel="cancel"
@open="open"
@close="close"
>
{{ props.item.name }}
<template v-slot:input>
<v-text-field
v-model="props.item.name"
:rules="[max25chars]"
label="Edit"
single-line
counter
></v-text-field>
</template>
</v-edit-dialog>
</template>
</v-data-table>
<v-snackbar v-model="snack" :timeout="3000" :color="snackColor">
{{ snackText }}
<template v-slot:action="{ attrs }">
<v-btn v-bind="attrs" text @click="snack = false">Close</v-btn>
</template>
</v-snackbar>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
snack: false,
snackColor: "",
snackText: "",
max25chars: (v) => v.length <= 25 || "Input too long!",
pagination: {},
headers: [
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
],
desserts: [
{
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 237,
fat: 9.0,
},
{
name: "Eclair",
calories: 262,
fat: 16.0,
},
],
};
},
methods: {
save() {
this.snack = true;
this.snackColor = "success";
this.snackText = "Data saved";
},
cancel() {
this.snack = true;
this.snackColor = "error";
this.snackText = "Canceled";
},
open() {
this.snack = true;
this.snackColor = "info";
this.snackText = "Dialog opened";
},
close() {
console.log("Dialog closed");
},
},
};
</script>
to make the name
column editable.
We have the v-edit-dialog
that has the input
slot populated with the v-text-field
component to let us edit the text when we click on the cell.
The rules
prop lets us set the validation rules.
We either return undefined
or an error message if there is one.
CRUD Actions
We can add a dialog box that opens when we click on a button in a table row.
To do that, we write:
<template>
<v-data-table :headers="headers" :items="desserts" sort-by="calories" class="elevation-1">
<template v-slot:top>
<v-toolbar flat color="white">
<v-toolbar-title>My CRUD</v-toolbar-title>
<v-divider class="mx-4" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-dialog v-model="dialog" max-width="500px">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark class="mb-2" v-bind="attrs" v-on="on">New Item</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.name" label="Dessert name"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.calories" label="Calories"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.fat" label="Fat (g)"></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="close">Cancel</v-btn>
<v-btn color="blue darken-1" text @click="save">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:item.actions="{ item }">
<v-icon small class="mr-2" @click="editItem(item)">mdi-pencil</v-icon>
<v-icon small @click="deleteItem(item)">mdi-delete</v-icon>
</template>
<template v-slot:no-data>
<v-btn color="primary" @click="initialize">Reset</v-btn>
</template>
</v-data-table>
</template>
<script>
export default {
name: "HelloWorld",
data: () => ({
dialog: false,
headers: [
{
text: "Dessert (100g serving)",
align: "start",
sortable: false,
value: "name",
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
{ text: "Actions", value: "actions", sortable: false },
],
desserts: [],
editedIndex: -1,
editedItem: {
name: "",
calories: 0,
fat: 0,
carbs: 0,
protein: 0,
},
defaultItem: {
name: "",
calories: 0,
fat: 0,
carbs: 0,
protein: 0,
},
}),
computed: {
formTitle() {
return this.editedIndex === -1 ? "New Item" : "Edit Item";
},
},
watch: {
dialog(val) {
val || this.close();
},
},
created() {
this.initialize();
},
methods: {
initialize() {
this.desserts = [
{
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
},
{
name: "Ice cream sandwich",
calories: 237,
fat: 9.0,
},
{
name: "Eclair",
calories: 262,
fat: 16.0,
},
];
},
editItem(item) {
this.editedIndex = this.desserts.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialog = true;
},
deleteItem(item) {
const index = this.desserts.indexOf(item);
confirm("Are you sure you want to delete this item?") &&
this.desserts.splice(index, 1);
},
close() {
this.dialog = false;
this.$nextTick(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1;
});
},
save() {
if (this.editedIndex > -1) {
Object.assign(this.desserts[this.editedIndex], this.editedItem);
} else {
this.desserts.push(this.editedItem);
}
this.close();
},
},
};
</script>
We populate the top
slot with our dialog box.
The dialog
state lets us control when it’s open.
When we click on the pencil button, the editItem
method is run.
this.editedIndex
is set and the this.editedItem
object is set so that the form will be populated with the values.
Also, when we click on the trash can button, we run the deleteItem
method.
We show the confirm dialog box and remove the item with the given index.
Conclusion
We can add and remove items from a table with some methods.
Also, we can edit column content by clicking on a cell with the v-edit-dialog
component.